package main;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class Main {

    public static void main(String[] args) {
//        testStudent_All_Field();
//
//        testStudent_Method_To_Method();
//
//        testStudent_Field_And_Method();
//
//        testStudent_Field_To_Field_Method();
//
//        testStudent_All_Field_Method();

        //---------------------------------------------------

        //testStudent_All_Field_Method_Inclded();

        timeCalc();
    }

    //----------------------------------------------------------
    //耗时计算
    static void timeCalc() {
        List<Student> list = new ArrayList<>();
        for (int i = 0; i <= 99; i++) {
            Student s = Init();
            list.add(s);
        }
        Student e = new Student();
        long all = 0;
        for (int j = 0; j <= list.size() - 1; j++) {
            Timestamp start = new Timestamp(new Date().getTime());
            ObjectHelper.copyFieldValues(list.get(j), e);
            Timestamp end = new Timestamp(new Date().getTime());
            System.out.println(String.format("第%d次耗时=%d毫秒", j, end.getTime() - start.getTime()));
            all += (end.getTime() - start.getTime());
            break;
        }

        System.out.println(String.format("平均耗时:%s毫秒", String.valueOf(all / list.size())));
    }
    static Student Init() {
        Student s = new Student();
        s.name = "francis";
        List<Method> tmpMethods = _getAllMethodsFromObjectClass(s.getClass());
        int i = 0;
        Object value = null;
        for (Method method : tmpMethods) {
            if (_isSetMethodToBeCopiedValue(method)) {
                value = "name" + i++;
                try {
                    method.invoke(s, value);
                } catch (IllegalAccessException e) {
                    //e.printStackTrace();
                } catch (InvocationTargetException e) {
                    //e.printStackTrace();
                }
            }
        }
        return s;
    }
    private static List<Method> _getAllMethodsFromObjectClass(Class objClass) {
        if (objClass == null) {
            return null;
        }
        List<Method> tmpResults = new ArrayList<Method>();
        //所有公用（public）方法包括其继承类的公用方法，
        // 当然也包括它所实现接口的方法。
        Method[] tmpMethods1 = objClass.getMethods();
        if (tmpMethods1 != null && tmpMethods1.length > 0) {
            for (Method m : tmpMethods1) {
                tmpResults.add(m);
            }
        }
        //对象表示的类或接口声明的所有方法，包括公共、保护、默认（包）访问和私有方法，
        // 但不包括继承的方法。当然也包括它所实现接口的方法。
        Method[] tmpMethods2 = objClass.getClass().getDeclaredMethods();
        if (tmpMethods2 != null && tmpMethods2.length > 0) {
            for (Method m : tmpMethods2) {
                tmpResults.add(m);
            }
        }
        return tmpResults;
    }
    private static boolean _isSetMethodToBeCopiedValue(Method method) {
        if (method == null) {
            return false;
        }
        String strMethodName = method.getName().toLowerCase();
        if (strMethodName.length() <= 3) {
            return false;
        }
        if (!strMethodName.startsWith("set")) {
            return false;
        }
        return _canCopied(method.getModifiers());
    }
    private static boolean _canCopied(int modifier) {
        if (Modifier.isFinal(modifier)) {
            return false;
        }
        if (Modifier.isPrivate(modifier)) {
            return false;
        }
        if (Modifier.isAbstract(modifier)) {
            return false;
        }
        if (Modifier.isNative(modifier)) {
            return false;
        }
        return true;
    }
    //-----------------------------------------------------------
    //from to 都是纯粹字段的情况 field-to-field
    static void testStudent_All_Field_Exclude() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_All_Field to = new Student_All_Field();
        ObjectHelper.copyFieldValuesExcludeFields(from, to, Arrays.asList("name"));

        if (from.no.equals(to.no) && (to.name==null)) {
            System.out.println("testStudent_All_Field_Exclude Passed");
        } else {
            System.out.println("testStudent_All_Field_Exclude Failed");
            System.out.println(to.no);
            System.out.println(to.name);
        }
    }

    //from: 字段， to： method field-to-method
    static void testStudent_Method_To_Method_Exclude() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_All_Method to = new Student_All_Method();
        ObjectHelper.copyFieldValuesExcludeFields(from, to, Arrays.asList("name"));

        if (from.no.equals(to.getNo()) && (to.getName()==null || to.getName().length()==0)) {
            System.out.println("testStudent_Method_To_Method_Exclude Passed");
        } else {
            System.out.println("testStudent_Method_To_Method_Exclude Failed");
            System.out.println(to.getNo());
            System.out.println(to.getName());
        }
    }

    //from: 字段， to： field+method
    static void testStudent_Field_And_Method_Exclude() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValuesExcludeFields(from, to, Arrays.asList("name"));

        if (from.no.equals(to.getNo()) && (to.name==null)) {
            System.out.println("testStudent_Field_And_Method_Exclude Passed");
        } else {
            System.out.println("testStudent_Field_And_Method_Exclude Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

    //from: method， to： field+method
    static void testStudent_Field_To_Field_Method_Exclude() {
        Student_All_Method from = new Student_All_Method();
        from.setName("francis");
        from.setNo("123456");
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValuesExcludeFields(from, to, Arrays.asList("name"));

        if (from.getNo().equals(to.getNo()) && (to.name==null)) {
            System.out.println("testStudent_Field_To_Field_Method_Exclude Passed");
        } else {
            System.out.println("testStudent_Field_To_Field_Method_Exclude Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

    //from/to field+ method
    static void testStudent_All_Field_Method_Exclude() {
        Student_Field_And_Method from = new Student_Field_And_Method();
        from.name = "francis";
        from.setNo("123456");
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValuesExcludeFields(from, to, Arrays.asList("no"));

        if ((to.getNo()==null) && from.name.equals(to.name)) {
            System.out.println("testStudent_All_Field Passed");
        } else {
            System.out.println("testStudent_All_Field Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

    //-----------------------------------------------------------
    //from to 都是纯粹字段的情况 field-to-field
    static void testStudent_All_Field_Inclded() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_All_Field to = new Student_All_Field();
        ObjectHelper.copyFieldValuesIncludeFields(from, to, Arrays.asList("no"));

        if (from.no.equals(to.no) && (to.name==null)) {
            System.out.println("testStudent_All_Field_Inclded Passed");
        } else {
            System.out.println("testStudent_All_Field_Inclded Failed");
            System.out.println(to.no);
            System.out.println(to.name);
        }
    }

    //from: 字段， to： method field-to-method
    static void testStudent_Method_To_Method_Inclded() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_All_Method to = new Student_All_Method();
        ObjectHelper.copyFieldValuesIncludeFields(from, to, Arrays.asList("no"));

        if (from.no.equals(to.getNo()) && (to.getName()==null || to.getName().length()==0)) {
            System.out.println("testStudent_Method_To_Method_Inclded Passed");
        } else {
            System.out.println("testStudent_Method_To_Method_Inclded Failed");
            System.out.println(to.getNo());
            System.out.println(to.getName());
        }
    }

    //from: 字段， to： field+method
    static void testStudent_Field_And_Method_Inclded() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValuesIncludeFields(from, to, Arrays.asList("no"));

        if (from.no.equals(to.getNo()) && (to.name==null)) {
            System.out.println("testStudent_Field_And_Method_Inclded Passed");
        } else {
            System.out.println("testStudent_Field_And_Method_Inclded Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

    //from: method， to： field+method
    static void testStudent_Field_To_Field_Method_Inclded() {
        Student_All_Method from = new Student_All_Method();
        from.setName("francis");
        from.setNo("123456");
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValuesIncludeFields(from, to, Arrays.asList("no"));

        if (from.getNo().equals(to.getNo()) && (to.name==null)) {
            System.out.println("testStudent_Field_To_Field_Method_Inclded Passed");
        } else {
            System.out.println("testStudent_Field_To_Field_Method_Inclded Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

    //from/to field+ method
    static void testStudent_All_Field_Method_Inclded() {
        Student_Field_And_Method from = new Student_Field_And_Method();
        from.name = "francis";
        from.setNo("123456");
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValuesIncludeFields(from, to, Arrays.asList("name"));

        if ((to.getNo()==null) && from.name.equals(to.name)) {
            System.out.println("testStudent_All_Field_Method_Inclded Passed");
        } else {
            System.out.println("testStudent_All_Field_Method_Inclded Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }


    //-----------------------------------------------------------


    //from to 都是纯粹字段的情况 field-to-field
    static void testStudent_All_Field() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_All_Field to = new Student_All_Field();
        ObjectHelper.copyFieldValues(from, to);

        if (from.no.equals(to.no)) {
            System.out.println("testStudent_All_Field Passed");
        } else {
            System.out.println("testStudent_All_Field Failed");
            System.out.println(to.no);
            System.out.println(to.name);
        }
    }

    //from: 字段， to： method field-to-method
    static void testStudent_Method_To_Method() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_All_Method to = new Student_All_Method();
        ObjectHelper.copyFieldValues(from, to);

        if (from.no.equals(to.getNo())) {
            System.out.println("testStudent_All_Field Passed");
        } else {
            System.out.println("testStudent_All_Field Failed");
            System.out.println(to.getNo());
            System.out.println(to.getName());
        }
    }

    //from: 字段， to： field+method
    static void testStudent_Field_And_Method() {
        Student_All_Field from = new Student_All_Field();
        from.name = "francis";
        from.no = "123456";
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValues(from, to);

        if (from.no.equals(to.getNo()) && from.name.equals(to.name)) {
            System.out.println("testStudent_All_Field Passed");
        } else {
            System.out.println("testStudent_All_Field Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

    //from: method， to： field+method
    static void testStudent_Field_To_Field_Method() {
        Student_All_Method from = new Student_All_Method();
        from.setName("francis");
        from.setNo("123456");
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValues(from, to);

        if (from.getNo().equals(to.getNo()) && from.getName().equals(to.name)) {
            System.out.println("testStudent_All_Field Passed");
        } else {
            System.out.println("testStudent_All_Field Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

    //from/to field+ method
    static void testStudent_All_Field_Method() {
        Student_Field_And_Method from = new Student_Field_And_Method();
        from.name = "francis";
        from.setNo("123456");
        Student_Field_And_Method to = new Student_Field_And_Method();
        ObjectHelper.copyFieldValues(from, to);

        if (from.getNo().equals(to.getNo()) && from.name.equals(to.name)) {
            System.out.println("testStudent_All_Field Passed");
        } else {
            System.out.println("testStudent_All_Field Failed");
            System.out.println(to.getNo());
            System.out.println(to.name);
        }
    }

}
